1.概述 | 2.我的第一个项目 | 3.模型 | 4.视图 | 5.列表数据 | 6.对象/关系映射 | 7.控制器 | 8.应用 | 9.定制

第 2章: 我的第一个OX项目

新建项目

先打开Eclipse将工作空间指向OpenXava 分发包中包含的workspace.
利用合适的Eclipse向导新建Java项目命名为 Management. 在工作空间中出现一个新的空白java文件, 下面步骤可将其转化为OpenXava 项目形式.
转到 OpenXavaTemplate 用Ant执行CreateNewProject.xml .用 右键 CreateNewProject.xml > Run as > Ant Build. Ant 提示项目名称, 输入 Management.
选择项目Management 然后按F5 进行刷新.
现在你有了一个马上可以工作的新项目, 但在开始之前你需要先配置好数据库.

配置数据库

OpenXava 生成的JavaEE/J2EE应用可以发布到Java Application Server中 (在v2.0 版本后OpenXava应用也可以运行在类似tomcat的简单servlet container中). 在OpenXava中你只需要指出Data Source JNDI 然后配置应用服务器的数据源. 如何配置应用服务器的数据源不在本文讲解的范围, 但你可以根据下面的提示来配置数据库,使用包含在OpenXava分发包中的Tomcat作为应用服务器,Hypersonic 作为数据源来运行你的第一各项目。Tomcat在文件夹openxava-3.x/tomcat下。
在Tomcat 停止的状态下编辑Tomcat下目录conf中的文件context.xml . 在文件中键入下列内容:
<Resource name="jdbc/ManagementDS" auth="Container" type="javax.sql.DataSource"
 maxActive="20" maxIdle="5" maxWait="10000"
 username="sa" password="" driverClassName="org.hsqldb.jdbcDriver"
 url="jdbc:hsqldb:hsql://localhost:1666"/>
这里最主要的是JNDI 名称, 这是OpenXava中引用的唯一名称, 在这里是 ManagementDS. 而driverClassNameurl 属性 取决与数据库, 在这里采用的是 Hypersonic.

你的第一个业务组件

创建OpenXava业务组件非常简单:每个组件都是一个带注解的Java类. 一开始你需要创建一个名为Warehouse的类:
  • src 文件夹下使用 右键 > New > Package
  • 创建一个包命名为org.openxava.management.model
  • 在包上 org.openxava.management.model 使用 右键 > New > Class
  • 新建类命名为Warehouse
现在编辑你的类,写下如下代码:
package org.openxava.management.model;
import javax.persistence.*;
import org.openxava.annotations.*;
@Entity
public class Warehouse {
 @Id @Column(length=3) @Required
 private int number;
 @Column(length=40) @Required
 private String name;
 public int getNumber() {
 return number;
 }
 public void setNumber(int number) {
 this.number = number;
 }
 public String getName() {
 return name;
 }
 public void setName(String name) {
 this.name = name;
 }
}
这个类包含(或即将包含) 应用程序所需要的与 Warehouse 业务概念有关的所有信息. 当前我们只有数据结构, 但在这个类中你还可以定义与数据库的映射关系,业务逻辑,可视化展现方式,列表数据管理等。
实际上这个类是遵循EJB3 标准的Entity. 要将一个类定义为 entity 你只需要在类声明中使用注解(annotation).
在entity 中你定义一系列属性(properties),如下:
@Id // 1
@Column(length=3) // 2
@Required // 3
private int number; // 4
private int getNumber() { // 4
 return number;
}
private void setNumber(int number) { // 4
 this.number = number;
}
注解的含义:
  1. **@Id: 表示本属性是键值的组成部分. 键是对象的唯一标识,通常与数据库表格中的主键相对应。
  2. **@Column(length= ): 数据的长度. 这是可选的, 但是对于展现更好的用户界面和生成数据库表有用。
  3. **@Required: 表示在创建或更新对象前需要验证本属性是否有值。
  4. Java类中的属性按照通常方式定义. 所有 Java 属性的有效类型都使用, 包括integrated types, JDK classes 和custom classes.
类型定义的可能性远比上面展示的多,你可以在 Model 章节中看到更详尽的描述.

数据表

在测试应用程序之前,你需要先在数据库中创建表. 执行如下操作:
  • 启动数据库服务器: 在命令行中指向 openxava-3.x/tomcat/bin 文件夹然后执行:
    • Linux/Unix: ./start-hsqldb.sh management-db 1666
    • Windows: start-hsqldb management-db 1666
  • 创建表:
    • 编辑Management/build.xml. 查找ant target updateSchema.
    • 输入合适的值schema.path, 在这里“../OpenXavaTest/lib/hsqldb.jar”.
    • 执行 ant target updateSchema.
  • 运行tomcat, 如果已经启动的话请重启, 现在一切就绪.

运行应用系统

经过一系列艰苦的工作,现在是时候检验你汗水的结晶了. 好,开始.
现在你可以运行你的模块(module)查看效果了.
你也可以将模块发布为 JSR-168 portlet:
  • 执行 ant target generatePortlets.
  • 将文件夹中 openxava-3.x/workspace.dist/Management.dist 的文件 Management.war 发布到你的Portal 服务器上.

测试自动化

虽然测试应用系统最自然的方式就是浏览器像最终用户一样操作,但自动化测试效率更高。采用自动化测试的方法,随着系统规模的增长,始终保持测试用例与应用系统一致,避免后期的开发破坏前期的工作.
OpenXava 采用基于JUnit 和 HttpUnit的测试系统. OpenXava JUnit 测试模拟实际用户使用浏览器的行为.用这种方式你可以准确重现你利用internet浏览器进行的操作.这种方法的优点在于你可以很容易测试应用程序中从用户界面到数据库的所有层次。
如果你手工测试一个模块,一般你会创建一条记录,查询这条记录,修改它,最后删除它。下面我们将这一过程自动化:
首先为测试类创建一个包, org.openxava.management.tests, 然后在包中添加WarehouseTest 类, 代码如下:
package org.openxava.management.tests;
import org.openxava.tests.*;
/**
 * @author Javier Paniza
 */
public class WarehouseTest extends ModuleTestBase {
 public WarehouseTest(String testName) {
 super(testName, "Management", "Warehouse"); // 1
 }
 public void testCreateReadUpdateDelete() throws Exception {
 // Create
 execute("CRUD.new"); // 2
 setValue("number", "7"); // 3
 setValue("name", "JUNIT Warehouse");
 execute("CRUD.save");
 assertNoErrors(); // 4
 assertValue("number", ""); // 5
 assertValue("name", "");
 // Read
 setValue("number", "7");
 execute("CRUD.search");
 assertValue("number", "7");
 assertValue("name", "JUNIT Warehouse");
 // Update
 setValue("name", "JUNIT Warehouse MODIFIED");
 execute("CRUD.save");
 assertNoErrors();
 assertValue("number", "");
 assertValue("name", "");
 // Verify if modified
 setValue("number", "7");
 execute("CRUD.search");
 assertValue("number", "7");
 assertValue("name", "JUNIT Warehouse MODIFIED");
 // Delete
 execute("CRUD.delete");
 assertMessage("Warehouse deleted successfully"); // 6
 }
}
在这个例子中你可以学到:
  1. 构造函数(Constructor): 在构造函数中指明应用系统和模块名称.
  2. 执行(execute): 模拟按钮或链接点击. 你发送动作名称作为参数,你可以查看OpenXava/xava/default-controllers.xml (预先定义好的) 和 Management/xava/controllers.xml (后来定制的). 你也可以将鼠标移动到链接上,浏览器就会显示要执行的JavaScript 代码,其中就包含要执行的OpenXava 动作. 例如execute(“CRUD.new”) 就像在用户界面中点击 'new' 按钮效果是一样的。
  3. 设定值(setValue): 给表单中的控件赋值. 例如, setValue(“name”, “Pepe”) 与在字段'name' 中敲入文本 “Pepe”是一个效果. 值都采用字符的形式,因为最终他们都赋值给 HTML 表单.
  4. 无错断言(assertNoErrors): 确认没有错误.在用户界面中错误用红色字体的消息形式显示给用户。错误一般是违反应用程序逻辑造成的。
  5. 值断言(assertValue): 确认表单中的值是所期望的值.
  6. 消息断言(assertMessage**): 确认应用程序显示了指定的消息。.
你可以很容易检测一个模块能够正常运行。 写这些代码可能需要花费5分钟, 但后来你能节省几个小时,因为从现在开始你测试这个模块只需要1秒钟时间,而且只要你破坏了 Warehouse 模块(可能由于动了应用程序的其他部分) 你写的测试用例就能及时提醒你.
要了解细节可以查看 org.openxava.tests.ModuleTestBase的JavaDoc API 或查看 OpenXavaTest的org.openxava.test.tests .
默认情况下测试在单独 (非portal) 模式(也就是用deployWar方式发布). 但如果你希望在the portlet 版本(用generatePortlets方式发布). 你只需要编辑文件properties/xava-junit.properties 添加这样一行代码:
liferay.url=web/guest
这是在Liferay下测试. 你也可以在JetSpeed2 portal下测试, 查看OpenXavaTest/properties/xava-junit.properties 以了解更多细节.

标签

现在一切正常,但还有一些细节需要处理。你很可能需要定义显示给最终用户的标签。将所有标签写到一个文件中,你可以将你的产品翻译成另一种语言.
要定义标签你只需要编辑在i18n 目录下的文件 Management-labels_en.properties. 编辑文件,添加:
Warehouse=Warehouse
你不需要加入所有属性, 因为常用的名称(数字, 名称, 描述等等) 已经翻译成 English, Spanish, Polish, French, German, Indonesian and Catalan多种语言包含OpenXava中.
如果你需要其他语言版本(以Spanish 为例), 你只需要复制粘贴然后改成合适的后缀. 例如, 你可以得到 Management-labels_es.properties 文件包含下面的内容:
Warehouse=Almacén
OpenXava 缺省的标签和消息在OpenXava/i18n/Labels.propertiesOpenXava/i18n/Messages.properties下. 如果你想改写这些资源,你不需要直接编辑这些文件,你可以在你的项目中使用相同的键值名称,然后你自己的标签和消息就代替了标准消息 (new in v2.0.3)。例如, 如果你想改变列表状态下的消息 ''There are 23663 objects in list”, 你需要在Management-messages_en.properties中增加下列内容:
# list_count is in Messages_en.properties of OpenXava, this is an example
# of overriding a standard openxava message
list_count=There are {0} records in list
现在你的应用系统就显示“There are 23663 records in list” 而不显示默认的 OpenXava 消息“'There are 23663 objects in list”.
如果你想了解定义OpenXava 元素标签的更多知识,请查看OpenXavaTest/i18n中的有关内容.